import os
from typing import Optional, Any
from django.contrib.contenttypes.fields import ContentType, GenericForeignKey
from django.db import models
from django.conf import settings
from django.utils.translation import gettext_lazy as _
import uuid

class FileManager(models.Manager):
    def get_for_object(self, obj: Optional[Any], relation_name: Optional[str] = None):
        queryset = self
        if obj:
            content_type = ContentType.objects.get_for_model(obj)
            queryset = self.filter(
                object_content_type=content_type,
                object_id=obj.id
            )
        if relation_name is not None:
            queryset = queryset.filter(
                relation_name=relation_name
            )
        return queryset.all()

    def delete_for_object(self, obj, relation_name: Optional[str] = None):
        files = self.get_for_object(obj, relation_name)
        files.delete()

class File(models.Model):
    """
    Model for storing uploaded files with user permissions and metadata
    """
    objects = FileManager()
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    file = models.FileField(max_length = 500)
    filename = models.CharField(max_length=255)
    content_type = models.CharField(max_length=100)
    file_size = models.PositiveBigIntegerField(editable=False)
    uploaded_at = models.DateTimeField(auto_now_add=True)

    object_content_type = models.ForeignKey(
        ContentType,
        null = True,
        on_delete=models.CASCADE
    )
    object_id = models.CharField(max_length=255, null=True)
    content_object = GenericForeignKey('object_content_type', 'object_id')
    relation_name = models.CharField(max_length=50)  # e.g., 'attachments'
    
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='owned_files'
    )
    allowed_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='accessible_files',
        blank=True
    )

    is_public = models.BooleanField(default=False)
    
    class Meta:
        indexes = [
            models.Index(fields=['object_content_type', 'object_id']),
            models.Index(fields=['relation_name']),
        ]
        ordering = ['-uploaded_at']
        default_permissions = []
        db_table = "file"
        verbose_name = _("文件")
        verbose_name_plural = verbose_name

    def save(self, *args, **kwargs):
        # Update file size on save
        if self.file:
            self.file_size = self.file.size
            super().save(*args, **kwargs)

    def can_access(self, user):
        """
        Check if a user has permission to access this file
        NOTE this is a rough check. For example, in the following condition, you
        should apply other checks also:
        """
        return (
            self.is_public or
            user.is_superuser or
            user == self.owner or
            user in self.allowed_users.all() or
            (hasattr(self.content_object, 'can_access')
             and
             self.content_object.can_access(user))
        )
